package com.sky.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.*;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class DishServiceImpl implements DishService {
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 新增菜品和口味
     *
     * @param dishDTO
     */
    @Transactional//开启事务
    @Override
    public void saveDishAndFlavor(DishDTO dishDTO) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        dishMapper.saveDish(dish);
        //如果口味不为空才往下走
        if (dishDTO.getFlavors() != null && dishDTO.getFlavors().size() > 0) {
            List<DishFlavor> dishFlavors = dishDTO.getFlavors().stream().map(dishFlavor -> {
                dishFlavor.setDishId(dish.getId());
                return dishFlavor;
            }).collect(Collectors.toList());
            dishFlavorMapper.saveFlavors(dishFlavors);
        }
    }

    /**
     * 菜品分页查询
     *
     * @param dishPageQueryDTO
     * @return
     */
    @Override
    public PageResult page(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
        DishDTO dishDTO = new DishDTO();
        BeanUtils.copyProperties(dishPageQueryDTO,dishDTO);
        List<Dish> list = dishMapper.page(dishDTO);
        //这里将dish的属性复制到dishVO中,再根据dish表中的categoryId查询分类,将分类的名字设置到dishVO中
        List<DishVO> voList = list.stream().map(dish -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish, dishVO);
            Category category = categoryMapper.findById(dish.getCategoryId());
            dishVO.setCategoryName(category.getName());
            return dishVO;
        }).collect(Collectors.toList());
        PageInfo<Dish> pageInfo = new PageInfo<>(list);
        return new PageResult(pageInfo.getTotal(), voList);
    }

    /**
     * 删除菜品功能
     *
     * @param ids 要删除的id
     *            功能逻辑
     *            1.判断菜品状态,在售的不能删除
     *            2.查询有米有关联套餐,关联套餐的不能删除
     *            3.先删除菜品
     *            4.最后删除菜品的口味
     */
    @Transactional
    @Override
    public void delByIds(List<Long> ids) {
        //1.判断菜品状态,在售的不能删除
        ids.forEach(id -> {
            Dish dish = dishMapper.findById(id);
            //任何一个菜品在启用状态,直接抛出异常
            if (dish.getStatus() == StatusConstant.ENABLE) {
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        });
        //2.查询有米有关联套餐,关联套餐的不能删除
        ids.forEach(id -> {
            Integer count = setmealDishMapper.countByDishId(id);
            //任何一个菜品关联了套餐,直接抛出异常
            if (count > 0) {
                throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
            }
        });
        //3.先删除菜品
        dishMapper.delByIds(ids);
        //4.最后删除菜品的口味
        ids.forEach(id -> dishFlavorMapper.delByDishId(id));

    }

    /**
     * 根据id查询菜品功能
     *
     * @param id
     * @return
     */
    @Override
    public DishVO findById(Long id) {
        Dish dish = dishMapper.findById(id);
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish, dishVO);
        //根据categoryId查询菜品分类
        Category category = categoryMapper.findById(dish.getCategoryId());
        //根据dishId查询口味
        List<DishFlavor> flavors = dishFlavorMapper.findByDishId(id);
        dishVO.setCategoryName(category.getName());
        dishVO.setFlavors(flavors);
        return dishVO;
    }

    /**
     * 修改菜品信息功能
     *
     * @param dishDTO
     * 逻辑分析
     *     这里不光要修改菜品信息,还要修改对应的口味信息表
     *     由于不确认口味表做了什么操作,想法是直接删除原来的口味,将新的口味添加到口味表中
     *     需要同时完成,所以开启事务
     */
    @Transactional
    @Override
    public void update(DishDTO dishDTO) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO, dish);
        //先修改菜品的其它内容
        dishMapper.update(dish);
        //对应的套餐里的菜品信息也要修改
        setmealDishMapper.updateByDishId(dish);
        List<DishFlavor> flavors = dishDTO.getFlavors();
        //删除原来该菜品的口味
        dishFlavorMapper.delByDishId(dishDTO.getId());
        //要对口味的集合做一个判断,如果集合非空且大小>0,才执行添加口味
        if (flavors != null && flavors.size() > 0) {
            //这里有一个小bug,如果是新增的口味是没有dishId属性的,所以会报非空异常,需要遍历添加dishId
            flavors.forEach(flavor -> flavor.setDishId(dishDTO.getId()));
            //将新的口味添加到口味表
            dishFlavorMapper.saveFlavors(flavors);
        }
    }

    /**
     * 启售或停售菜品功能
     *
     * @param status
     * @param id
     * 需求:菜品停售的时候对应的套餐也要停售
     */
    @Transactional
    @Override
    public void enableOrDisable(Integer status, Long id) {
        //如果是菜品停售,对应的套餐也要停售
        if (status == StatusConstant.DISABLE) {
            //查询菜品想关联的套餐
            List<SetmealDish> list = setmealDishMapper.findByDishId(id);
            if (list != null && list.size() != 0) {
                list.forEach(setmealDish -> {
                    Setmeal setmeal = new Setmeal();
                    setmeal.setId(setmealDish.getSetmealId());
                    setmeal.setStatus(StatusConstant.DISABLE);
                    setmealMapper.update(setmeal);
                    //如果停售菜品,对应的套餐也会停售,这也也要清除套餐的缓存数据
                    Setmeal dbsetmeal = setmealMapper.findById(setmealDish.getSetmealId());
                    String CACHE_SETMEAL_KEY = "SETMEAL_" + dbsetmeal.getCategoryId();
                    redisTemplate.delete(CACHE_SETMEAL_KEY);
                });
            }
        }
        //将status和id封装到一个dish中
        Dish dish = new Dish();
        dish.setId(id);
        dish.setStatus(status);
        //直接调用修改菜品信息的sql
        dishMapper.update(dish);
    }

    /**
     * 根据分类id或名字查询菜品功能
     *
     * @param dishDTO
     * @return
     */
    @Override
    public List<DishVO> findByConditions(DishDTO dishDTO) {
        List<Dish> list = dishMapper.page(dishDTO);
        //写一个过滤器,只要在售状态的菜品
        List<DishVO> enableList = list.stream().
                filter(dish -> dish.getStatus() == StatusConstant.ENABLE)
                .map(dish -> {
                    DishVO dishVO = new DishVO();
                    BeanUtils.copyProperties(dish,dishVO);
                    return dishVO;
                }).collect(Collectors.toList());
        return enableList;
    }

    /**
     * 根据菜品id查询菜品和对应口味
     * @param dishDTO
     * @return
     */
    @Override
    public List<DishVO> listWithFlavor(DishDTO dishDTO) {
        List<Dish> dishList = dishMapper.page(dishDTO);
        List<DishVO> dishVOList = dishList.stream().map(dish -> {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(dish,dishVO);
            //根据菜品id查询对应的口味
            List<DishFlavor> flavors = dishFlavorMapper.findByDishId(dish.getId());
            dishVO.setFlavors(flavors);
            return dishVO;
        }).collect(Collectors.toList());
        return dishVOList;
    }
}
